package at.tetris4j.view;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Scanner;
import org.fusesource.jansi.Ansi;
import org.fusesource.jansi.Ansi.Color;
import org.fusesource.jansi.AnsiConsole;
import org.jnativehook.GlobalScreen;
import org.jnativehook.NativeHookException;
import at.tetris4j.commons.TetrisColor;
import at.tetris4j.controller.IController;
import at.tetris4j.helpers.Utils;
import at.tetris4j.model.IModel;
import at.tetris4j.model.components.BoardPresentation;
import at.tetris4j.view.utils.GameState;
import at.tetris4j.view.utils.GlobalKeyListener;
import at.tetris4j.view.utils.TetrisKey;
public class TetrisView implements IConsoleView {
private static final char SPACE_CHARACTER = ' ';
private static final char LINE_CHARACTER = '-';
private static final char WALL_CHARACTER = '|';
private static final char BLOCK_CHARACTER = '#';
private static final String IP_PATTERN = "^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
+ "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
+ "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
+ "([01]?\\d\\d?|2[0-4]\\d|25[0-5])$";
private final IController controller;
private GameState gameState = GameState.MainMenu;
public TetrisView(IController controller) {
this.controller = controller;
GlobalScreen.getInstance().addNativeKeyListener(new GlobalKeyListener(this));
}
@Override
public void showStartScreen() {
gameState = GameState.MainMenu;
AnsiConsole.out.print(Ansi.ansi().cursor(0, 0));
AnsiConsole.out.print(Ansi.ansi().eraseScreen());
String[] heading = Utils.readLines("/heading.txt");
for (String s : heading) {
AnsiConsole.out.println(Ansi.ansi().fg(Color.YELLOW).a("\t" + s).reset());
}
AnsiConsole.out.println();
AnsiConsole.out.println();
AnsiConsole.out.println();
String[] menu = Utils.readLines("/menu.txt");
for (String s : menu) {
AnsiConsole.out.println(Ansi.ansi().fg(Color.BLUE).a(s).reset());
}
}
@Override
public void keyPressed(TetrisKey key) {
switch (key) {
case UP:
if (gameState == GameState.SinglePlayer
|| gameState == GameState.Multiplayer)
controller.upPressed();
break;
case DOWN:
if (gameState == GameState.SinglePlayer
|| gameState == GameState.Multiplayer)
controller.downPressed();
break;
case LEFT:
if (gameState == GameState.SinglePlayer
|| gameState == GameState.Multiplayer)
controller.moveLeft();
break;
case RIGHT:
if (gameState == GameState.SinglePlayer
|| gameState == GameState.Multiplayer)
controller.moveRight();
break;
case PAUSE:
controller.pauseGame();
break;
case RESUME:
controller.resumeGame();
break;
case STOP:
controller.stopGame();
break;
case FUNCTIONKEY_1:
if (gameState == GameState.MainMenu) {
gameState = GameState.SinglePlayer;
controller.startSinglePlayerMode();
AnsiConsole.out.print(Ansi.ansi().eraseScreen());
} else if (gameState == GameState.NetworkInput) {
gameState = GameState.Multiplayer;
controller.startMultiplayerMode();
}
break;
case FUNCTIONKEY_2:
if (gameState == GameState.MainMenu) {
gameState = GameState.Multiplayer;
controller.multiplayerPressed();
} else if (gameState == GameState.NetworkInput) {
getIpFromUser();
}
break;
default:
break;
}
}
private void getIpFromUser() {
GlobalScreen.unregisterNativeHook();
Scanner scanner = new Scanner(System.in);
String ip;
do {
System.out.println();
System.out.println("PLEASE TYPE IN YOUR OPPONENTS IP ADDRESS: ");
ip = scanner.next();
}
while(!ip.matches(IP_PATTERN));
try {
InetAddress ipAddress = InetAddress.getByName(ip);
System.out.println(ipAddress.toString());
controller.startMultiplayerMode(ipAddress);
this.gameState = GameState.Multiplayer;
} catch (UnknownHostException e) {
System.out.println("could not find host " + e);
controller.stopGame();
} finally {
scanner.close();
registerNativeHook();
}
}
@Override
public void clear() {
AnsiConsole.out.print(Ansi.ansi().eraseScreen());
}
@Override
public void updateScreen(IModel model) {
AnsiConsole.out.print(Ansi.ansi().cursor(0, 0));
BoardPresentation boardPresentation = model.getGameBoard();
printGameBoardPresentation(boardPresentation);
if (gameState == GameState.Multiplayer) {
AnsiConsole.out.print(Ansi.ansi().cursor(0, 50));
BoardPresentation player2BoardPresentation = model.getOtherBoardPresentation();
if(player2BoardPresentation != null)
AnsiConsole.out.print(player2BoardPresentation.getOutput());
}
}
private void printGameBoardPresentation(BoardPresentation boardPresentation) {
final int[][] board = boardPresentation.getPresentation();
final int height = board.length;
final int width = board[0].length;
for (int i = 0; i <= width + 1; i++) {
AnsiConsole.out.print(LINE_CHARACTER);
}
AnsiConsole.out.println();
for (int y = 0; y < height; y++) {
AnsiConsole.out.print(WALL_CHARACTER);
for (int x = 0; x < width; x++) {
int val = board[y][x];
if (val != 0) {
Color color = mapColorToValue(val);
AnsiConsole.out.print(Ansi.ansi().fg(color).a(BLOCK_CHARACTER).reset());
} else {
AnsiConsole.out.print(SPACE_CHARACTER);
}
}
AnsiConsole.out.println(WALL_CHARACTER);
}
for (int i = 0; i <= width + 1; i++) {
AnsiConsole.out.print(LINE_CHARACTER);
}
AnsiConsole.out.println();
}
private Color mapColorToValue(int rgbVal) {
TetrisColor tetrisColor = TetrisColor.getColorByRgb(rgbVal);
switch (tetrisColor) {
case RED:
return Color.RED;
case BLUE:
return Color.BLUE;
case CYAN:
return Color.CYAN;
case GREEN:
return Color.GREEN;
case MAGENTA:
return Color.MAGENTA;
case WHITE:
return Color.WHITE;
case YELLOW:
return Color.YELLOW;
default:
return Color.DEFAULT;
}
}
@Override
public void showNetworkInfoScreen() {
gameState = GameState.NetworkInput;
AnsiConsole.out.print(Ansi.ansi().cursor(0, 0));
AnsiConsole.out.print(Ansi.ansi().eraseScreen());
String[] networkInfo = Utils.readLines("/network.txt");
for (String s : networkInfo) {
AnsiConsole.out.println(Ansi.ansi().fg(Color.GREEN).a("\t\t" + s).reset());
}
}
@Override
public void showGameOverScreen() {
AnsiConsole.out.print(Ansi.ansi().cursor(0, 0));
AnsiConsole.out.print(Ansi.ansi().eraseScreen());
String[] goodbyeString = Utils.readLines("/gameover.txt");
for (String s : goodbyeString) {
AnsiConsole.out.println(Ansi.ansi().fg(Color.RED).a("\t" + s).reset());
}
unregisterNativeHook();
}
@Override
public void showGoodbyeScreen() {
AnsiConsole.out.print(Ansi.ansi().cursor(0, 0));
AnsiConsole.out.print(Ansi.ansi().eraseScreen());
String[] goodbyeString = Utils.readLines("/goodbye.txt");
for (String s : goodbyeString) {
AnsiConsole.out.println(Ansi.ansi().fg(Color.GREEN).a("\t" + s).reset());
}
unregisterNativeHook();
}
private void registerNativeHook() {
try {
GlobalScreen.registerNativeHook();
} catch (NativeHookException e) {
System.out.println("native hook could not be registered");
controller.stopGame();
}
}
private void unregisterNativeHook() {
GlobalScreen.unregisterNativeHook();
}
}